package com.seal.commons.infrastructure.redis.configuration;

import com.seal.commons.infrastructure.facade.distributed.lock.DistributedLock;
import com.seal.commons.infrastructure.facade.distributed.lock.annotation.DistributeLock;
import com.seal.commons.utils.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.context.annotation.Configuration;

import java.util.Arrays;

@Aspect
@Configuration
@ConditionalOnClass(DistributedLock.class)
@AutoConfigureAfter(DistributedAutoConfiguration.class)
public class DistributedLockAspectConfiguration {

    private final Logger logger = LoggerFactory.getLogger(DistributedLockAspectConfiguration.class);

    @Autowired
    private DistributedLock redisDistributedLock;

    @Around("@annotation(redisLock)")
    public Object around(ProceedingJoinPoint pjp, DistributeLock redisLock) throws Throwable{
        if(!DistributeLock.LockType.REDIS.equals(redisLock.type())){
            return pjp.proceed();
        }
        String key = redisLock.value();
        if(StringUtils.isEmpty(key)){
            Object[] args = pjp.getArgs();
            key = Arrays.toString(args);
        }
        int retryTimes = redisLock.action().equals(DistributeLock.LockFailAction.CONTINUE) ? redisLock.retryTimes() : 0;
        final  String finalKey = key;
        return redisDistributedLock.acquire(finalKey, redisLock.keepMills(), retryTimes, redisLock.sleepMills(), ()->{
            try {
                return pjp.proceed();
            } catch (Throwable throwable) {
                logger.error("redis distributedLock acquire error, key:{}", finalKey, throwable);
            }
            return null;
        });
    }
}


